﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using NeuralNetworks.Neurons;

namespace NeuralNetworks.Layers
{
    public abstract class Layer
    {
        public List<Neuron> Neurons;

        private double _minRandom = -1.0, _maxRandom = 1.0;
        private string name;

        public Neuron this[int index]
        {
            get { return Neurons[index]; }
        }

        public int NeuronsCount
        {
            get { return Neurons.Count; }
        }

        public double MaxRandom
        {
            get { return _maxRandom; }
            set { _maxRandom = value; }
        }

        public double MinRandom
        {
            get { return _minRandom; }
            set { _minRandom = value; }
        }

        public Layer(int nneurons, string name)
        {
            if((nneurons < 1)){ throw (new NeuralNetworksException()); };
            Neurons = new List<Neuron>(nneurons);
            this.name = name;
        }

        public void ConnectWithLayer(Layer l)
        {
            if (l == null) { throw (new NeuralNetworksException()); };
            foreach (Neuron n in Neurons)
            {
                n.AddInputs(l);
            }
            RandomWeights(new Random());
        }

        public void RandomWeights(Random r)
        {
            if (r == null) { throw (new NeuralNetworksException()); };
            foreach (Neuron n in Neurons)
            {
                n.RandomWeights(_minRandom, _maxRandom, r);
            }
        }

        public void ZeroWeights()
        {
            foreach (Neuron n in Neurons)
            {
                n.ZeroWeights();
            }
        }

        public virtual void SetOutputs(double[] output)
        {
            if ((output == null) || (output.Length != Neurons.Count))
            { throw (new NeuralNetworksException()); }

            for (int i = 0; i < Neurons.Count; i++)
            {
                ((Neuron)Neurons[i]).Output = output[i];
            }
        }

        public virtual double[] Outputs()
        {
            double[] result = new double[Neurons.Count];
            for (int i = 0; i < Neurons.Count; i++)
            {
                result[i] = ((Neuron)Neurons[i]).Output;
            }
            return result;
        }

        public virtual void Compute()
        {
            foreach (Neuron n in Neurons)
            {
                n.Compute();
            }
        }


        override public string ToString()
        {
            return this.name;
        }
    }
}
